#include "netclient.h"
#include <QUuid>
#include "../model/datacenter.h"
#include "../toast.h"
namespace network
{


NetClient::NetClient(model::DataCenter* const dataCenter)
    :dataCenter(dataCenter)
{

}

void NetClient::ping()
{
    QNetworkRequest httpReq;
    httpReq.setUrl(QUrl(HTTP_URL+"/ping"));

    QNetworkReply* httpRsp = httpClient.get(httpReq);
    connect(httpRsp,&QNetworkReply::finished,this,[=]()
    {
        if(httpRsp->error()!=QNetworkReply::NoError)
        {
            LOG()<<"HTTP 请求失败:"<<httpRsp->errorString();
            httpRsp->deleteLater();
            return;
        }
        QByteArray body = httpRsp->readAll();
        LOG()<<"响应内容:"<<body;
        httpRsp->deleteLater();
    });
}
QString NetClient::makeRequestId()
{
    return "R"+QUuid::createUuid().toString().sliced(25,12);
}

void NetClient::sendAuth()
{
    zzy_mims::ClientAuthenticationReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(dataCenter->getLoginSessionId());
    QByteArray body = req.serialize(&serializer);
    websocketClient.sendBinaryMessage(body);
    LOG()<<"[WS身份认证] requestId="<<req.requestId()<<",loginSessionId = "<<req.sessionId();
}


QNetworkReply* NetClient::sendHttpRequest(const QString& apiPath, const QByteArray& body)
{
    QNetworkRequest httpReq;
    httpReq.setUrl(HTTP_URL+apiPath);
    httpReq.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-protobuf");
    QNetworkReply* httpRep = httpClient.post(httpReq,body);
    return httpRep;
}

void NetClient::getMyself(const QString& loginSessionId)
{
    //1.构造HTTP请求的body
    zzy_mims::GetUserInfoReq req;
    req.setRequestId(makeRequestId());
    req.setSessionId(loginSessionId);
    QByteArray body = req.serialize(&serializer);
    LOG()<<"[获取个人信息] 发送请求,requestId = "<<req.requestId()<<",loginSessionId="<<loginSessionId;
    //2.构造HTTP请求，并发送出去
    QNetworkReply* httpRep = sendHttpRequest("/service/user/get_user_info",body);
    //3.通过信号槽，获取当前响应
    connect(httpRep,&QNetworkReply::finished,this,[=]
    {
        bool ok = false;
        QString reason;
        //判断执行是否正确，并将传入的应答的反序列结果返回
        auto resp = handleHttpResponse<zzy_mims::GetUserInfoRsp>(httpRep,ok,reason);
        if(!ok)
        {
            LOG()<<"[获取个人信息] 出错，requestId = "<<req.requestId()<<"reason = "<<reason;
            return;
        }
        dataCenter->resetMyself(resp);
        emit dataCenter->getMyselfDone();
        LOG()<<"[获取个人信息] 从网络获取信息成功! requestId="<<req.requestId();
    });

}

void NetClient::getSessionList(const QString &loginSessionId)
{
    //1. 通过pb构造body
    zzy_mims::GetChatSessionListReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    QByteArray body = pbReq.serialize(&serializer);
    LOG()<<"[获取会话列表] 发送请求 requestId = " <<pbReq.requestId()<<", loginSessionId="<<loginSessionId;

    //2. 发送HTTP请求
    QNetworkReply* httprep = sendHttpRequest("/service/friend/get_chat_session_list",body);

    //3. 针对响应进行处理
    connect(httprep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::GetChatSessionListRsp>(httprep,ok,reason);
        if(!ok)
        {
            LOG()<<"[获取会话列表] 失败,reason = "<<reason;
            return;
        }
        dataCenter->resetSessionList(pbRsp);
        emit dataCenter->getSessionListDone();
        LOG()<<"[获取会话列表] 处理响应完毕，requestId = "<<pbReq.requestId();
    });

}

void NetClient::getFriendList(const QString &loginSessionId)
{

    //1. 通过pb构造body
    zzy_mims::GetFriendListReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    QByteArray body = pbReq.serialize(&serializer);
    LOG()<<"[获取好友列表] 发送请求 requestId = " <<pbReq.requestId()<<", loginSessionId="<<loginSessionId;

    //2. 发送HTTP请求
    QNetworkReply* httprep = sendHttpRequest("/service/friend/get_friend_list",body);

    //3. 针对响应进行处理
    connect(httprep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::GetFriendListRsp>(httprep,ok,reason);
        if(!ok)
        {
            LOG()<<"[获取好友列表] 失败,reason = "<<reason;
            return;
        }
        dataCenter->resetFriendList(pbRsp);
        emit dataCenter->getFriendListDone();
        LOG()<<"[获取好友列表] 处理响应完毕，requestId = "<<pbReq.requestId();
    });

}

void NetClient::getApplyList(const QString &loginSessionId)
{
    //1.通过pb构造body
    zzy_mims::GetPendingFriendEventListReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    QByteArray body = pbReq.serialize(&serializer);
    LOG()<<"[获取好友申请列表] 发送请求 requestId = " <<pbReq.requestId()<<", loginSessionId="<<loginSessionId;

    //2.发送HTTP请求
    QNetworkReply* httpRep = sendHttpRequest("/service/friend/get_pending_friend_events",body);

    //3.针对响应进行处理
    connect(httpRep,&QNetworkReply::finished,this,[=]()
    {
        bool ok =false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::GetPendingFriendEventListRsp>(httpRep,ok,reason);

        if(!ok)
        {
            LOG()<<"[获取好友申请列表] 失败,reason = "<<reason;
            return;
        }
        dataCenter->resetApplyList(pbRsp);
        emit dataCenter->getApplyListDone();
        LOG()<<"[获取好友申请列表] 处理响应完毕，requestId = "<<pbReq.requestId();

    });

}

void NetClient::getRecentMessageList(const QString &loginSessionId, const QString &sessionId, bool isUpdateUI)
{
    //1.通过pb构造body
    zzy_mims::GetRecentMsgReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    pbReq.setMsgCount(50);
    pbReq.setChatSessionId(sessionId);
    QByteArray body = pbReq.serialize(&serializer);
    LOG()<<"[获取最近消息列表] 发送请求 requestId = " <<pbReq.requestId()<<", loginSessionId="<<loginSessionId;

    //2.发送HTTP请求
    QNetworkReply* httpRep = sendHttpRequest("/service/message_storage/get_recent",body);

    //3.针对响应进行处理
    connect(httpRep,&QNetworkReply::finished,this,[=]()
    {
        bool ok =false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::GetRecentMsgRsp>(httpRep,ok,reason);
        if(!ok)
        {
            LOG()<<"[获取最近消息列表] 失败,reason = "<<reason;
            return;
        }
        dataCenter->resetRecentMessageList(pbRsp,sessionId);
        if(isUpdateUI)
            emit dataCenter->getRecentMessageDone(sessionId);
        else
            emit dataCenter->getRecentMessageDoneNoUi(sessionId);
        LOG()<<"[获取最近消息列表] 处理响应完毕，requestId = "<<pbReq.requestId();

    });


}

void NetClient::sendMessage(const QString &loginSessionId, const QString &sessionId, model::MessageType msgType, const QByteArray &cont, const QString &extraInfo)
{
    //1.构建HTTP请求
    zzy_mims::NewMessageReq pbReq;
    pbReq.setChatSessionId(sessionId);
    pbReq.setSessionId(loginSessionId);
    pbReq.setRequestId(makeRequestId());

    zzy_mims::MessageContent msgContent;
    switch(msgType)
    {
        case model::MessageType::TEXT_TYPE:
        {
            zzy_mims::StringMessageInfo sMsg;
            sMsg.setContent(cont);
            msgContent.setStringMessage(sMsg);
            msgContent.setMessageType(zzy_mims::MessageTypeGadget::STRING);
            break;
        }
        case model::MessageType::IMAGE_TYPE:
        {
            zzy_mims::ImageMessageInfo iMsg;
            iMsg.setImageContent(cont);
            iMsg.setFileId("");//fileId是在服务器生成的，客户端不需要设置具体值
            msgContent.setImageMessage(iMsg);
            msgContent.setMessageType(zzy_mims::MessageTypeGadget::IMAGE);
            break;
        }
        case model::MessageType::SPEECH_TYPE:
        {
            zzy_mims::SpeechMessageInfo sMsg;
            sMsg.setFileContents(cont);
            sMsg.setFileId("");//fileId是在服务器生成的，客户端不需要设置具体值
            msgContent.setSpeechMessage(sMsg);
            msgContent.setMessageType(zzy_mims::MessageTypeGadget::SPEECH);
            break;
        }
        case model::MessageType::FILE_TYPE:
        {
            zzy_mims::FileMessageInfo fMsg;
            fMsg.setFileContents(cont);
            fMsg.setFileName(extraInfo);
            fMsg.setFileSize(cont.size());
            fMsg.setFileId("");//fileId是在服务器生成的，客户端不需要设置具体值
            msgContent.setFileMessage(fMsg);
            msgContent.setMessageType(zzy_mims::MessageTypeGadget::FILE);
            break;
        }
        default:
        {
            LOG()<<"错误的消息类型，messageType:"<<(int)msgType;
        }
    }

    pbReq.setMessage(msgContent);
    LOG()<<"[发送信息] 发送请求，loginSessionId="<<loginSessionId<<",sessionId="<<sessionId
          <<",messageType="<<(int)msgType<<",requestId="<<pbReq.requestId();
    QByteArray body=pbReq.serialize(&serializer);

    //2.发送请求
    QNetworkReply* httpRep = sendHttpRequest("/service/message_transmit/new_message",body);
    //3.处理响应
    connect(httpRep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::NewMessageRsp>(httpRep,ok,reason);
        if(!ok)
        {
            LOG()<<"[发送信息] 失败,reason = "<<reason;
            return;
        }

        emit dataCenter->sendMessageDone(msgType,cont,extraInfo);

        LOG()<<"[发送信息] 处理响应完毕，requestId = "<<pbReq.requestId();

    });
}
void NetClient::changeNickname(const QString &loginSessionId, const QString &nickname)
{
    zzy_mims::SetUserNicknameReq pbReq;
    pbReq.setNickname(nickname);
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    const QByteArray body = pbReq.serialize(&serializer);

    LOG()<<"[修改姓名] 发送请求loginSessionId="<<loginSessionId<<",newNickname:"<<nickname;

    QNetworkReply* rep = sendHttpRequest("/service/user/set_nickname",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        QString reason;
        bool ok = false;
        auto pbRsp = handleHttpResponse<zzy_mims::SetUserNicknameRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[修改姓名]失败,reason:"<<reason;
            return;
        }
        dataCenter->setNickname(nickname);
        emit dataCenter->changeNicknameDone();
        LOG()<<"[修改姓名] 处理完毕,requestId="<<pbReq.requestId();

    });
}

void NetClient::changeDesc(const QString &loginSessionId, const QString &desc)
{
    zzy_mims::SetUserDescriptionReq pbReq;
    pbReq.setDescription(desc);
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[修改签名] 发送请求 loginSessionId="<<loginSessionId<<",newDesc:"<<desc;
    QNetworkReply* rep = sendHttpRequest("/service/user/set_description",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        QString reason;
        bool ok = false;
        auto pbRsp = handleHttpResponse<zzy_mims::SetUserDescriptionRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[修改签名] 错误，reason:"<<reason;
            return;
        }
        dataCenter->setDesc(desc);
        emit dataCenter->changeDescDone();
        LOG()<<"[修改签名]完毕，requestId:"<<pbReq.requestId();
    });
}

void NetClient::getVertifyCode(const QString &phone)
{
    zzy_mims::PhoneVerifyCodeReq pbReq;
    pbReq.setPhoneNumber(phone);
    pbReq.setRequestId(makeRequestId());
    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[获取验证码] 发送请求，phone:"<<phone;
    QNetworkReply* rep = sendHttpRequest("/service/user/get_phone_verify_code",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::PhoneVerifyCodeRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[获取验证码]请求失败，reason:"<<reason<<",phone:"<<phone;
            return;
        }
        dataCenter->setCurrentVerifyCodeId(pbRsp->verifyCodeId());
        //这里保存手机号的原因是，防止发送验证码时输入的手机号，和点击确定按钮时输入的手机号不一致
        dataCenter->setPhoneToChange(phone);
        emit dataCenter->getVerifyCodeDone();
        LOG()<<"[获取验证码] 请求成功，phone:"<<phone;
    });
}

void NetClient::changePhone(const QString &loginSessionId, const QString &phone, const QString &verifyCodeId, const QString &verifyCode)
{
    zzy_mims::SetUserPhoneNumberReq pbReq;
    pbReq.setPhoneNumber(phone);
    pbReq.setSessionId(loginSessionId);
    pbReq.setRequestId(makeRequestId());
    pbReq.setPhoneVerifyCode(verifyCode);
    pbReq.setPhoneVerifyCodeId(verifyCodeId);
    LOG()<<"[修改手机号]请求， newPhone:"<<phone<<", loginSessionId:"<<loginSessionId;
    const QByteArray& body= pbReq.serialize(&serializer);
    QNetworkReply* rep = sendHttpRequest("/service/user/set_phone",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::SetUserPhoneNumberRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[修改手机号]请求失败， reason:"<<reason<<",newPhone:"<<phone<<", requestId:"<<pbReq.requestId();
            return;
        }
        dataCenter->setPhone(phone);
        emit dataCenter->changePhoneDone();
        LOG()<<"[修改手机号]完毕， newPhone:"<<phone<<", requestId:"<<pbReq.requestId();
    });

}

void NetClient::changeAvatar(const QString &loginSessionId, const QByteArray &avatar)
{
    zzy_mims::SetUserAvatarReq pbReq;
    pbReq.setAvatar(avatar);
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[修改头像]请求loginSessionId:"<<loginSessionId;
    QNetworkReply* rep =sendHttpRequest("/service/user/set_avatar",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::SetUserAvatarRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[修改头像]请求失败 reason:"<<reason<<",requestId:"<<pbReq.requestId();
            return;
        }
        dataCenter->setAvatar(avatar);
        emit dataCenter->changeAvatarDone();
        LOG()<<"[修改头像]请求成功 requestId:"<<pbReq.requestId();
    });

}

void NetClient::deleteFriend(const QString &loginSessionId, const QString &userId)
{
    zzy_mims::FriendRemoveReq pbReq;
    pbReq.setUserId(dataCenter->getMyself()->userId);
    pbReq.setPeerId(userId);
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[删除好友] 发送请求，requestId="<<pbReq.requestId()<<",deleteUserId="<<userId;

    QNetworkReply* rep = sendHttpRequest("/service/friend/remove_friend",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::FriendRemoveRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[删除好友] 发送请求失败，reason:"<<reason<<",requestId="<<pbReq.requestId()<<",deleteUserId="<<userId;
            return;
        }
        dataCenter->removeFriend(userId);
        //槽在mainWidget中
        emit dataCenter->deleteFriendDone();
        LOG()<<"[删除好友] 完毕，requestId="<<pbReq.requestId()<<",deleteUserId="<<userId;
    });
}

void NetClient::sendApply(const QString &loginSessionId, const QString &userId)
{
    zzy_mims::FriendAddReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setRespondentId(userId);
    pbReq.setUserId(dataCenter->getMyself()->userId);
    pbReq.setSessionId(loginSessionId);
    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[发送好友申请] 发送申请，requestId="<<pbReq.requestId()<<"发送者:"
          <<dataCenter->getMyself()->userId<<"接受者"<<userId;
    QNetworkReply* rep = sendHttpRequest("/service/friend/add_friend_apply",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::FriendAddRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[发送好友申请] 发送申请失败，reason:"<<reason<<",requestId="<<pbReq.requestId()<<"发送者:"
                  <<dataCenter->getMyself()->userId<<"接受者"<<userId;
            return;
        }
        Toast::showMessage("申请发送成功");
        LOG()<<"[发送好友申请]完毕，requestId="<<pbReq.requestId()<<"发送者:"
            <<dataCenter->getMyself()->userId<<"接受者"<<userId;
    });
}

void NetClient::processFriendApply(const QString &loginSessionId,const QString& applyUserId,bool isAgree)
{
    zzy_mims::FriendAddProcessReq pbReq;
    pbReq.setAgree(isAgree);
    pbReq.setApplyUserId(applyUserId);
    pbReq.setUserId(dataCenter->getMyself()->userId);
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[处理好友申请] 发送申请，requestId="<<pbReq.requestId()<<"发送者:"
          <<applyUserId<<"处理者"<<dataCenter->getMyself()->userId;
    QNetworkReply* rep = sendHttpRequest("/service/friend/add_friend_process",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::FriendAddProcessRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[处理好友申请] 发送申请失败，reason:"<<reason<<",requestId="<<pbReq.requestId()<<"发送者:"
                  <<applyUserId<<"处理者"<<dataCenter->getMyself()->userId;
            return;
        }
        const model::UserInfo& applyUserInfo =  dataCenter->removeFromApplyList(applyUserId);
        if(isAgree)
            dataCenter->addFriend(applyUserInfo);

        emit dataCenter->processFriendApplyDone();
        LOG()<<"[处理好友申请] 完毕，requestId="<<pbReq.requestId()<<"发送者:"
              <<applyUserId<<"处理者"<<dataCenter->getMyself()->userId;
    });
}

void NetClient::sreachUser(const QString &loginSessionId, const QString &key)
{
    zzy_mims::FriendSearchReq pbReq;
    pbReq.setSearchKey(key);
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    pbReq.setUserId(dataCenter->getMyself()->userId);
    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[用户搜索申请] 发送申请，requestId="<<pbReq.requestId()<<"用户:"
          <<pbReq.userId()<<"key:"<<pbReq.searchKey();
    QNetworkReply* rep =  sendHttpRequest("/service/friend/search_friend",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::FriendSearchRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[用户搜索申请] 失败，reason:"<<reason<<"，requestId="<<pbReq.requestId()<<"用户:"
                  <<pbReq.userId()<<"key:"<<pbReq.searchKey();
            return;
        }
        dataCenter->resetSearchResult(pbRsp->userInfo());
        emit dataCenter->searchUserDone();
        LOG()<<"[用户搜索申请] 完毕，requestId="<<pbReq.requestId()<<"用户:"
              <<pbReq.userId()<<"key:"<<pbReq.searchKey();
    });
}

void NetClient::createSession(const QString &loginSessionId,const QList<QString> &memberList)
{
    zzy_mims::ChatSessionCreateReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    //创建群聊设置为固定的名字，后面用户再修改
    pbReq.setChatSessionName("新的群聊");
    pbReq.setMemberIdList(memberList);
    pbReq.setUserId(dataCenter->getMyself()->userId);
    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[创建群聊] 发送申请，requestId="<<pbReq.requestId()<<"用户:"
          <<pbReq.userId()<<"memberList:"<<memberList;
    QNetworkReply* rep =  sendHttpRequest("/service/friend/create_chat_session",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::ChatSessionCreateRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[创建群聊] 失败，reason:"<<reason<<"，requestId="<<pbReq.requestId()<<"用户:"
                  <<pbReq.userId()<<"memberList:"<<memberList;
            return;
        }

        LOG()<<"[创建群聊] 完毕，requestId="<<pbReq.requestId()<<"用户:"
              <<pbReq.userId()<<"memberList:"<<memberList;
    });
}

void NetClient::getSessionMemberList(const QString &loginSessionId, const QString &sessionId)
{
    zzy_mims::GetChatSessionMemberReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    pbReq.setChatSessionId(sessionId);
    pbReq.setUserId(dataCenter->getMyself()->userId);

    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[加载群聊成员] 发送申请，requestId="<<pbReq.requestId()<<"用户:"
          <<pbReq.userId()<<"sessionId:"<<sessionId;
    QNetworkReply* rep =  sendHttpRequest("/service/friend/get_chat_session_member",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::GetChatSessionMemberRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[加载群聊成员] 失败，reason:"<<reason<<"，requestId="<<pbReq.requestId()<<"用户:"
                  <<pbReq.userId()<<"sessionId:"<<sessionId;
            return;
        }
        dataCenter->resetSessionMemberList(sessionId,pbRsp->memberInfoList());
        emit dataCenter->getSessionMemberListDone(sessionId);

        LOG()<<"[加载群聊成员] 完毕，requestId="<<pbReq.requestId()<<"用户:"
              <<pbReq.userId()<<"sessionId:"<<sessionId;
    });
}

void NetClient::getSearchHistoryList(const QString &loginSessionId, const QString &key)
{
    zzy_mims::MsgSearchReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    pbReq.setSearchKey(key);
    pbReq.setUserId(dataCenter->getMyself()->userId);
    pbReq.setChatSessionId(dataCenter->getCurrentSessionId());

    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[搜索历史消息] 发送申请，requestId="<<pbReq.requestId()<<"用户:"
          <<pbReq.userId()<<"sessionId:"<<pbReq.chatSessionId()<<"key:"<<pbReq.searchKey();
    QNetworkReply* rep =  sendHttpRequest("/service/message_storage/search_history",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::MsgSearchRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[搜索历史消息] 失败，reason:"<<reason<<"，requestId="<<pbReq.requestId()<<"用户:"
                  <<pbReq.userId()<<"sessionId:"<<pbReq.chatSessionId()<<"key:"<<pbReq.searchKey();
            return;
        }
        dataCenter->resetSearchHistoryList(pbRsp->msgList());
        emit dataCenter->getSearchHistoryListDone();

        LOG()<<"[搜索历史消息] 完毕，requestId="<<pbReq.requestId()<<"用户:"
              <<pbReq.userId()<<"sessionId:"<<pbReq.chatSessionId()<<"key:"<<pbReq.searchKey();
    });
}

void NetClient::getSearchHistoryListByTime(const QDateTime &beginTime, const QDateTime &endTime, const QString &loginSessionId)
{
    zzy_mims::GetHistoryMsgReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSessionId(loginSessionId);
    pbReq.setStartTime(beginTime.toSecsSinceEpoch());
    pbReq.setOverTime(endTime.toSecsSinceEpoch());
    pbReq.setUserId(dataCenter->getMyself()->userId);
    pbReq.setChatSessionId(dataCenter->getCurrentSessionId());

    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[搜索历史消息] 发送申请，requestId="<<pbReq.requestId()<<"用户:"
          <<pbReq.userId()<<"sessionId:"<<pbReq.chatSessionId()<<"初始时间:"
          <<beginTime<<"结束时间:"<<endTime;
    QNetworkReply* rep =  sendHttpRequest("/service/message_storage/get_history",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::GetHistoryMsgRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[搜索历史消息] 失败，reason:"<<reason<<"，requestId="<<pbReq.requestId()<<"用户:"
                  <<pbReq.userId()<<"sessionId:"<<pbReq.chatSessionId()<<"初始时间:"
                  <<beginTime<<"结束时间:"<<endTime;
            return;
        }
        dataCenter->resetSearchHistoryList(pbRsp->msgList());
        emit dataCenter->getSearchHistoryListDone();

        LOG()<<"[搜索历史消息] 完毕，requestId="<<pbReq.requestId()<<"用户:"
              <<pbReq.userId()<<"sessionId:"<<pbReq.chatSessionId()<<"初始时间:"
              <<beginTime<<"结束时间:"<<endTime<<"搜索个数:"<<pbRsp->msgList().size();
    });
}

void NetClient::userLogin(const QString &name, const QString &pswd)
{
    zzy_mims::UserLoginReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setNickname(name);
    pbReq.setPassword(pswd);
    pbReq.setVerifyCode("");
    pbReq.setVerifyCodeId("");

    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[用户登录] 发送申请，requestId="<<pbReq.requestId()<<"用户:"
          <<pbReq.nickname()<<"密码:"<<pbReq.password();
    QNetworkReply* rep =  sendHttpRequest("/service/user/username_login",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::UserLoginRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[用户登录] 失败，reason:"<<reason<<"，requestId="<<pbReq.requestId()<<"用户:"
                  <<pbReq.nickname()<<"密码:"<<pbReq.password();
            Toast::showMessage("用户名或密码错误");
            return;
        }

        dataCenter->setLoginSessionId(pbRsp->loginSessionId());
        emit dataCenter->userLoginDone();

        LOG()<<"[用户登录] 完毕，requestId="<<pbReq.requestId()<<"用户:"
              <<pbReq.nickname()<<"密码:"<<pbReq.password();
    });
}

void NetClient::userRegister(const QString &name, const QString &pswd)
{
    zzy_mims::UserRegisterReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setNickname(name);
    pbReq.setPassword(pswd);
    pbReq.setVerifyCode("");
    pbReq.setVerifyCodeId("");

    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[用户注册] 发送申请，requestId="<<pbReq.requestId()<<"用户:"
          <<pbReq.nickname()<<"密码:"<<pbReq.password();
    QNetworkReply* rep =  sendHttpRequest("/service/user/username_register",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::UserRegisterRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[用户注册] 失败，reason:"<<reason<<"，requestId="<<pbReq.requestId()<<"用户:"
                  <<pbReq.nickname()<<"密码:"<<pbReq.password();
            Toast::showMessage("用户名或密码错误");
            return;
        }

        emit dataCenter->userRegisterDone();

        LOG()<<"[用户注册] 完毕，requestId="<<pbReq.requestId()<<"用户:"
              <<pbReq.nickname()<<"密码:"<<pbReq.password();
    });

}

void NetClient::phoneLogin(const QString &phone, const QString &verifyCodeId, const QString &verifyCode)
{
    zzy_mims::PhoneLoginReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setPhoneNumber(phone);
    pbReq.setVerifyCode(verifyCode);
    pbReq.setVerifyCodeId(verifyCodeId);

    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[手机号登录] 发送申请，requestId="<<pbReq.requestId()<<"手机号:"
          <<pbReq.phoneNumber()<<"验证码:"<<pbReq.verifyCode();
    QNetworkReply* rep =  sendHttpRequest("/service/user/phone_login",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::PhoneLoginRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[手机号登录] 失败，reason:"<<reason<<"，requestId="<<pbReq.requestId()<<"手机号:"
                  <<pbReq.phoneNumber()<<"验证码:"<<pbReq.verifyCode();
            Toast::showMessage("输入错误");
            return;
        }
        dataCenter->setLoginSessionId(pbRsp->loginSessionId());
        emit dataCenter->phoneLoginDone();
        LOG()<<"[手机号登录] 完毕，requestId="<<pbReq.requestId()<<"手机号:"
              <<pbReq.phoneNumber()<<"验证码:"<<pbReq.verifyCode();
    });
}

void NetClient::phoneRegister(const QString &phone, const QString &verifyCodeId, const QString &verifyCode)
{
    zzy_mims::PhoneRegisterReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setPhoneNumber(phone);
    pbReq.setVerifyCode(verifyCode);
    pbReq.setVerifyCodeId(verifyCodeId);
    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[手机号注册] 发送申请，requestId="<<pbReq.requestId()<<"手机号:"
          <<pbReq.phoneNumber()<<"验证码:"<<pbReq.verifyCode();
    QNetworkReply* rep =  sendHttpRequest("/service/user/phone_register",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::PhoneRegisterRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[手机号注册] 失败，reason:"<<reason<<"，requestId="<<pbReq.requestId()<<"手机号:"
                  <<pbReq.phoneNumber()<<"验证码:"<<pbReq.verifyCode();
            Toast::showMessage("输入错误");
            return;
        }
        emit dataCenter->phoneRegisterDone();
        LOG()<<"[手机号注册] 完毕，requestId="<<pbReq.requestId()<<"手机号:"
              <<pbReq.phoneNumber()<<"验证码:"<<pbReq.verifyCode();
    });
}

void NetClient::getSingleFile(const QString &loginSessionId, const QString &fileId)
{
    zzy_mims::GetSingleFileReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setFileId(fileId);
    pbReq.setSessionId(loginSessionId);
    pbReq.setUserId(dataCenter->getMyself()->userId);
    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[获取单个文件] 发送申请，requestId="<<pbReq.requestId()<<"userId:"
          <<pbReq.userId()<<"fileId:"<<pbReq.fileId();
    QNetworkReply* rep =  sendHttpRequest("/service/file/get_single_file",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::GetSingleFileRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[获取单个文件] 失败，reason:"<<reason<<"，requestId="<<pbReq.requestId()<<"userId:"
                  <<pbReq.userId()<<"fileId:"<<pbReq.fileId();
            return;
        }
        emit dataCenter->getSingleFileDone(fileId,pbRsp->fileData().fileContent());
        LOG()<<"[获取单个文件] 完毕，requestId="<<pbReq.requestId()<<"userId:"
              <<pbReq.userId()<<"fileId:"<<pbReq.fileId();
    });
}

void NetClient::speechConvertText(const QString &loginSessionId, const QString &fileId, const QByteArray &content)
{
    zzy_mims::SpeechRecognitionReq pbReq;
    pbReq.setRequestId(makeRequestId());
    pbReq.setSpeechContent(content);
    pbReq.setSessionId(loginSessionId);
    pbReq.setUserId(dataCenter->getMyself()->userId);
    const QByteArray& body = pbReq.serialize(&serializer);
    LOG()<<"[语音转文字] 发送申请，requestId="<<pbReq.requestId()<<"userId:"
          <<pbReq.userId();
    QNetworkReply* rep =  sendHttpRequest("/service/speech/recognition",body);
    connect(rep,&QNetworkReply::finished,this,[=]()
    {
        bool ok = false;
        QString reason;
        auto pbRsp = handleHttpResponse<zzy_mims::SpeechRecognitionRsp>(rep,ok,reason);
        if(!ok)
        {
            LOG()<<"[语音转文字] 失败，reason:"<<reason<<"，requestId="<<pbReq.requestId()<<"userId:"
                  <<pbReq.userId();
            return;
        }
        //如果语音没有内容，就转成"嗯"(仿照微信)
        if(!pbRsp->hasRecognitionResult()||pbRsp->recognitionResult().isEmpty())
            pbRsp->setRecognitionResult("嗯");
        emit dataCenter->speechConvertTextDone(fileId,pbRsp->recognitionResult());

        LOG()<<"[语音转文字] 完毕，requestId="<<pbReq.requestId()<<"userId:"
              <<pbReq.userId();
    });
}

//////////////////////////////////////////////////
/// 下面是websocket相关
//////////////////////////////////////////////////

void NetClient::initWebSocket()
{
    //1.准备好所需的信号槽
    connect(&websocketClient,&QWebSocket::connected,this,[=]
    {
        LOG()<<"websocket连接成功";
        //连接成功后，发送身份认证消息
        sendAuth();
    });

    connect(&websocketClient,&QWebSocket::disconnected,this,[=]()
    {
        LOG()<<"websocket断开连接";
    });
    connect(&websocketClient,&QWebSocket::errorOccurred,this,[=](QAbstractSocket::SocketError error)
    {
        LOG()<<"websocket连接出错"<<error;
    });
    connect(&websocketClient,&QWebSocket::textMessageReceived,this,[=](const QString& message)
    {
        LOG()<<"websocket收到文本消息"<<message;
    });
    connect(&websocketClient,&QWebSocket::binaryMessageReceived,this,[=](const QByteArray& byteArray)
    {
        LOG()<<"websocket收到二进制消息"<<byteArray.length();
        zzy_mims::NotifyMessage notifyMessage;
        notifyMessage.deserialize(&serializer,byteArray);
        handleWSResponse(notifyMessage);
    });


    //和服务器建立联系
    websocketClient.open(WEBSOCKET_URL);

}

void NetClient::closeWebSocket()
{
    websocketClient.close();
    LOG()<<"关闭websocket";
}

void NetClient::handleWSResponse(const zzy_mims::NotifyMessage& notifyMessage)
{
    switch(notifyMessage.notifyType())
    {
        case zzy_mims::NotifyTypeGadget::CHAT_MESSAGE_NOTIFY:
        {
            model::Message msg;
            msg.load(notifyMessage.newMessageInfo().messageInfo());
            handleWSMessage(msg);
            break;
        }
        case zzy_mims::NotifyTypeGadget::FRIEND_ADD_APPLY_NOTIFY:
        {
            model::UserInfo userInfo;
            userInfo.load(notifyMessage.friendAddApply().userInfo());
            handleWSApply(userInfo);
            break;
        }
        case zzy_mims::NotifyTypeGadget::FRIEND_ADD_PROCESS_NOTIFY:
        {
            model::UserInfo userInfo;
            userInfo.load(notifyMessage.friendProcessResult().userInfo());
            handleWSProcess(userInfo,notifyMessage.friendProcessResult().agree());
            break;
        }
        case zzy_mims::NotifyTypeGadget::CHAT_SESSION_CREATE_NOTIFY:
        {
            model::SessionInfo sessionInfo;
            sessionInfo.load(notifyMessage.newChatSessionInfo().chatSessionInfo());
            handleWSCreateSession(sessionInfo);
            break;
        }
        default:
        {
            LOG()<<"收到了未知类型的通知"<<(long long)notifyMessage.notifyType();
        }
    }

}

void NetClient::handleWSMessage(const model::Message &msg)
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    QList<model::Message>* msgList = dataCenter->getRecentMessageList(msg.chatSessionId);
    if(msgList)
    {
        msgList->push_back(msg);
        receiveMessage(msg.chatSessionId);
    }
    else
    {
        connect(dataCenter,&model::DataCenter::getRecentMessageDoneNoUi,this,&NetClient::receiveMessage,Qt::UniqueConnection);
        getRecentMessageList(dataCenter->getLoginSessionId(),msg.chatSessionId,false);
    }
}

void NetClient::handleWSApply(const model::UserInfo &userInfo)
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    QList<model::UserInfo>* applyList= dataCenter->getApplyList();
    //如果applyList是空的，不需要处理，因为点击申请标签会自动从服务器获取,且不需要通知mainWidget更新界面
    if(applyList)
        applyList->push_front(userInfo);
    else
        return;
    //槽函数在mainWidget
    emit dataCenter->acceptFriendApplyDone();
}

void NetClient::handleWSProcess(const model::UserInfo &userInfo, bool isAgree)
{
    if(!isAgree) return;
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    dataCenter->addFriend(userInfo);
    emit dataCenter->processFriendApplyDone();
}
void NetClient::handleWSCreateSession(const model::SessionInfo &sessionInfo)
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    dataCenter->getSessionList()->push_front(sessionInfo);
    emit dataCenter->createSessionDone();
}

void NetClient::receiveMessage(const QString& sessionId)
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();
    if(sessionId==dataCenter->getCurrentSessionId())
    {
        const model::Message& msg = dataCenter->getRecentMessageList(sessionId)->back();
        //这个信号的槽在editArea区域内
        emit dataCenter->receiveMessageDone(msg);
    }
    else
    {
        dataCenter->addUnread(sessionId);
    }
    //这个信号的槽在showArea区域内
    emit dataCenter->updateLastMessage(sessionId);
}

}//network













